/*-------------------------------------------------------------------------
(C) COPYRIGHT 2021 Black Sesame Technologies (Shanghai) Co., Ltd. ALL RIGHTS RESERVED
Filename			:		libsecurity.h
Author				:		Xiaojun Zhang
Data				:		2023-5-16
Version				:		1.0
Description			:		
Modification History	:
Data			By			    Version			Change Description
===========================================================================
23/05/16		Xiaojun Zhang     1.0		    Original
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdint.h>


#ifndef __LIBSECURITY_H
#define __LIBSECURITY_H


#define RSA_NOPAD                       0x60000030      /*optee-CA RSA加解密填充方式*/
#define RSAES_PKCS1_V1_5                0x60000130
#define RSAES_PKCS1_OAEP_MGF1_SHA1      0x60210230
#define RSAES_PKCS1_OAEP_MGF1_SHA224    0x60310230
#define RSAES_PKCS1_OAEP_MGF1_SHA256    0x60410230
#define RSAES_PKCS1_OAEP_MGF1_SHA384    0x60510230
#define RSAES_PKCS1_OAEP_MGF1_SHA512    0x60610230
#define RSASSA_PKCS1_V1_5_MD5           0x70001830      /*optee-CA RSA签名验签填充方式*/
#define RSASSA_PKCS1_V1_5_SHA1          0x70002830
#define RSASSA_PKCS1_V1_5_SHA224        0x70003830
#define RSASSA_PKCS1_V1_5_SHA256        0x70004830
#define RSASSA_PKCS1_V1_5_SHA384        0x70005830
#define RSASSA_PKCS1_V1_5_SHA512        0x70006830
#define RSASSA_PKCS1_V1_5_MD5SHA1       0x7000F830
#define TEE_TYPE_SM2_DSA_PUBLIC_KEY     0xA0000045      /*optee-CA ECC秘钥类型*/
#define TEE_TYPE_SM2_DSA_KEYPAIR        0xA1000045      // Sign and verify
#define TEE_TYPE_SM2_KEP_PUBLIC_KEY     0xA0000046      // Derive shared key
#define TEE_TYPE_SM2_KEP_KEYPAIR        0xA1000046
#define TEE_TYPE_SM2_PKE_PUBLIC_KEY     0xA0000047      // Encrypt and decrypt
#define TEE_TYPE_SM2_PKE_KEYPAIR        0xA1000047

#define R5_USER_KEYID_MIN   0x12340000
#define R5_USER_KEYID_MAX   0x12340007
#define R5_USER_DERIVE_KEYID_MIN   0x12340000
#define R5_USER_DERIVE_KEYID_MAX   0x12340003

#define R5_KEY_BURNED       1
#define R5_KEY_NOT_BURNED   0xffffffff

#define USR_KEY_MAGIC 		0x12340000
#define OTP_KEY_MAGIC 		0xabcd0000
#define USE_USR_KEY 		0x10000
#define USE_QSPI_KEY 		0x20000

#ifndef DATA_MAX_LEN
#define DATA_MAX_LEN        0xFFFFFF   /*加解密数据最大长度*/
#endif 

#ifndef IVEC_LEN
#define IVEC_LEN            16         /*128bit 向量长度*/
#endif

#define R5_MAX_DATA_LEN 2088960

// OPTEE secure storage partition
#define STORAGE_SEC_REE     0x000A
#define STORAGE_SEC_RPMB    0x000B


typedef enum{
    SEC_MODULE_OPTEE = 0x0200,
    SEC_MODULE_R5 = 0x0300,
    SEC_MODULE_INVALID, //deprecated
}SEC_MODULE;//this enum type is deprecated, use macro CYBER_MODULE_XXX instead

#define CYBER_MODULE_OPTEE 0x0200
#define CYBER_MODULE_R5 0x0300


typedef enum {
    SEC_AES_DECRYPT = 0,
    SEC_AES_ENCRYPT = 1,
    SEC_AES_TYPE_INVALID
}SEC_AES_TYPE;

typedef enum {
    SEC_AES_CBC = 0,
    SEC_AES_CTR,
    SEC_AES_ECB,
    SEC_AES_MODE_INVALID
}SEC_AES_MODE;

typedef enum {
    SEC_AES_128_BIT = 16,         /*128bit 密钥长度*/
    SEC_AES_192_BIT = 24,         /*192bit 密钥长度*/
    SEC_AES_256_BIT = 32          /*256bit 密钥长度*/    
}SEC_AES_KEYLEN;

typedef enum{
    SEC_KEYMODE_NORMAL,         /*正常模式，传入key*/
    SEC_KEYMODE_R5SRAM = 1,     /*key存储在R5 SRAM*/
    SEC_KEYMODE_R5URK = 3,     /*key存储在R5 OTP-user root key*/
    SEC_KEYMODE_INVALID
}SEC_KEYMODE;

typedef enum  {
    SBL_KEY = 0xabcd0000, //SBL验签秘钥
    USER_ROOT_KEY = 0xabcd0001, //User Root Key
    SBR_HMAC_KEY = 0xabcd0004, //sbrHmac密钥
    SBR_AES_KEY = 0xabcd0005, //sbrAES密钥
}E_OTP_KEY_ID;
#define OTP_INQUIRE_FLAG 	0xcccc0000
	
typedef enum  {
    FORCE_OTP_KEY = 0xaaaa0000, 
    OTP_KEY_FLAG = 0xbbbb0000, //SBL验签秘钥
    EN_KDF_KEY = 0xdddd0002 //EN_HUK标志位
}E_KEY_FLAG_ID;
#define SPC_KEY_INQUIRE_FLAG    0xdddd0000

/*芯片生命周期状态值*/
typedef enum {
    STAGE_INIT = 0x24680000,
    STAGE_PILOT,
    STAGE_MASS, 
    STAGE_FAIL,
    STAGE_END,
    STAGE_DEV,
}E_LIFE_CYCLE;

typedef enum {
	MSHA_SHA1 = 0,
	MSHA_SHA224,
	MSHA_SHA256,
	MSHA_HMAC1,//3
	MSHA_HMAC224,
	MSHA_HMAC256
} E_MSHA_MODE;


#define SEC_ERROR_CODE_BEGIN    0x1000  /*安全模块错误码起始值*/
enum SEC_ERROR_CODE {
    SEC_SUCCESS = 0x0000,               /*成功*/
    SEC_NULL_POINTER_ERROR = SEC_ERROR_CODE_BEGIN,    /*0x1000 空指针*/
    SEC_LENGTH_ERROR,                   /*长度错误*/
    SEC_DATA_ERROR,                     /*数据错误*/
    SEC_MEMORY_NOT_ENOUGH,              /*内存不足*/
    SEC_FILE_OP_FAIL,                   /*文件操作失败*/
    SEC_INVALID_MODE,                   /*不支持的模式*/
    SEC_INIT_SESSION_FAIL,              /*CA session初始化失败*/
    SEC_OPEN_SESSION_FAIL,              /*CA session打开失败*/
    SEC_INVOKE_COMMAND_FAIL,            /*CA发送命令失败*/
    SEC_SEND_COMMAND_FAIL,              /*通用错误*/
    SEC_INVALID_MODULE,                /*不支持的模块*/
    SEC_IPC_SEND_MSG_FAIL,              /*IPC消息发送失败*/
    SEC_IPC_RECV_REG_TYPE_ERR,          /*IPC消息类型错误*/
    SEC_MMAP_DEV_MEM_FAIL,              /*MAP硬件地址失败*/
    SEC_MUNMAP_DEV_MEM_FAIL,            /*UNMAP硬件地址失败*/
    SEC_ITEM_NOT_FOUND,                 /*item没有找到*/
    SEC_KEY_LENGTH_NOTSUPPORT,            /*0x1010 不支持的KEY长度*/
    SEC_KEY_TYPE_NOTSUPPORT,              /*不支持的KEY类型*/
    SEC_GET_KEY_STATUS_FAIL,              /*获取key状态失败*/
    SEC_INVALIDE_STAGE,                  /*获取key状态失败*/
    SEC_HUK_IS_NOT_READY,               /*HUK未准备好*/
    SEC_ERROR_CODE_INVALID              /*错误码结束值*/
};

struct ver_info_args {
	uint32_t a0;	/* SMC function ID */
	uint32_t a1;	/* Parameter */
	uint32_t a2;	/* Parameter */
	uint32_t a3;	/* Thread ID when returning from RPC */
	uint32_t a4;	/* Not used */
	uint32_t a5;	/* Not used */
	uint32_t a6;	/* Not used */
	uint32_t a7;	/* Hypervisor Client ID */
};

typedef struct RSA_pub{
    char* modulus;
    size_t modu_len;
    char* pub_expo;
    size_t pub_len;
}RSA_pubkey;

typedef struct RSA_pri{
    char* modulus;
    size_t modu_len;
    char* pub_expo;
    size_t pub_len;
    char* pri_expo;
    size_t pri_len;
}RSA_prikey;

typedef struct ECC_pub{
    char* x;
    size_t x_len;
    char* y;
    size_t y_len;
}ECC_pubkey;

typedef struct ECC_pri{
    char* x;
    size_t x_len;
    char* y;
    size_t y_len;
    char* pri_val;
    size_t pri_len;
}ECC_prikey;

#if defined(__cplusplus)
extern "C" {
#endif


/*--------------------------------------------------------------------------------------
Function	: libsec_HD_RAND_bytes
Description : 生成硬件随机数随机数
Parameter	: buf:  出参，随机数存放地址（需保证内存大小大于等于num个Byte）
              num:  入参，要产生的随机数Byte数
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_HD_RAND_bytes(unsigned char *buf, unsigned int num);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_CRC_ex
Description : 硬件CRC32计算
Parameter	: data:     入参，数据地址
              dataLen:  入参，数据长度(1~2088960 bytes)
              mode:     入参，crc模式      0: Crc32 , 1: Crc32c, 2: Crc16
              initData: 入参，初始值       0: 0000, else: 0xffff
              refData:  入参，是否翻转     0: 不反转, else: 反转
              xorData:  入参，异或数据     0: 0000, else: 0xffff
              crc:      出参，crc结果
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_CRC_ex(unsigned char *data,unsigned int dataLen,unsigned int mode,unsigned int initData,
                    unsigned int refData,unsigned int xorData,unsigned int *crc);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_CRC32
Description : 硬件CRC32计算 equal to libsec_R5_CRC_ex(data,dataLen,0,0,0,0,crc)
Parameter	: data:     入参，数据地址
              dataLen:  入参，数据长度
              crc:      出参，crc结果
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_CRC32(unsigned char *data,unsigned int dataLen,unsigned int *crc);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_hash
Description : R5hash运算
Parameter	: data:     入参，数据地址
              dataLen:  入参，数据长度(1~2088960 bytes)
              mode:     入参，hash模式     0：SHA1, 1：SHA224, 2：SHA256
              hash:     出参，hash结果数据
              hashLen:  出入参，【入】hash结果buffer长度,【出】hash结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_hash(unsigned char *data,unsigned int dataLen,unsigned int mode,unsigned char *hash,unsigned int *hashLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_file_hash
Description : 硬件计算文件hash
Parameter	: filename: 入参，文件名
              mode:     入参，hash模式     0：SHA1, 1：SHA224, 2：SHA256
              hash:     出参，hash结果数据
              hashLen:  出入参，【入】hash结果buffer长度,【出】hash结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_file_hash(char* filename,unsigned int mode,unsigned char *hash,unsigned int *hashLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_HMAC
Description : 封装自R5接口，计算HMAC值
Parameter	: data:     入参，数据地址
              data_len: 入参，数据长度(1~2088960 bytes)
              key:      入参，传入的密钥
              keyLen:   入参，传入密钥的长度
              mode:     入参，hmac模式  3:HMAC1 4:HMAC224 5:HMAC256
              key_type: 入参，密钥类型
              key_idx:  入参，R5 SRAM中user key的序号  
                        当key_type=SEC_KEYMODE_R5SRAM时，选择user key的序号：0x12340000~0x12340007
              data_out: 出参，HMAC计算结果
              data_out_len:  出入参，【入】HMAC计算结果buffer长度,【出】HMAC实际计算结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_HMAC(unsigned char* data, unsigned int data_len, unsigned char* key, unsigned int key_len,
    E_MSHA_MODE mode, SEC_KEYMODE key_type, const int key_idx, unsigned char* data_out, unsigned int *data_out_len);
 
/*--------------------------------------------------------------------------------------
Function	: libsec_R5_RSA_EDN
Description : 根据E D N 值进行 R5 RSA加解密，R5采用小端字节序，所以注意所有参数的字节序调整
Parameter	: data:             入参，待加密数据
              dataLen:          入参，数据长度，与keyLen相同：
              key:              入参，秘钥，公钥为秘钥E值，私钥为密钥D值，注意：r5只支持512bit 1024bit 2048bit三种秘钥
              keyLen:           入参，秘钥长度
              mod:              入参，模值N数据
              modLen:           入参，模值N数据长度
              out：             出参，加密后数据
              outLen:           出入参，【入】out的buffer长度,【出】加密结果实际长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_RSA_EDN(unsigned char *data,unsigned int dataLen,
unsigned char *key,unsigned int keyLen,
unsigned char *mod,unsigned int modLen,
unsigned char *out, int *outLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_GetTmpEncryptedAESKey
Description : R5获取临时的被公钥加密的aes key (OTP加密烧录第一步)
Parameter	: pub:     入参，RSA2048 DER格式公钥数据地址
              pubLen:  入参，公钥数据长度
              key:     出参，被公钥加密的临时AES秘钥，解密后低32字节为随机数（AES的加密秘钥）,其余高位全为0。
                             注意：利用openssl或libcybersecurity解密后数据为大端字节序，应将字节串反转后取前32字节。
              keyLen:  出入参，【入】被公钥加密的临时AES秘钥buffer长度,【出】被公钥加密的临时AES秘钥实际长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_GetTmpEncryptedAESKey(unsigned char *pub,unsigned int pubLen,unsigned char *key,unsigned int *keyLen) ;

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_OTPWriteEncryptedKey
Description : R5烧写aes加密后的key(OTP加密烧录第二步)
              注意：一个临时秘钥只能烧写一次（每次烧写都要重新获取临时秘钥）
Parameter	: keyID:    入参，秘钥类型ID
                            0xabcd0000 (SBL_KEY) SBL验签秘钥，
                            0xabcd0001 (USER_ROOT_KEY) User Root Key，
                            0xabcd0004 (SBR_HMAC_KEY) sbrHmac密钥
                            0xabcd0005 (SBR_AES_KEY) sbrAES密钥
              key:      入参，被AES加密（密钥长度为256位，加密模式为AES_ECB，iv为全0）的秘钥数据
              keyLen:   入参，秘钥数据长度，目前只支持32字节
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_OTPWriteEncryptedKey(unsigned int keyID, unsigned char *key,unsigned int keyLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_SM3
Description : R5国密SM3运算
Parameter	: data:     入参，数据地址
              dataLen:  入参，数据长度
              out:     出参，SM3结果数据
              outLen:  出入参，【入】SM3结果buffer长度,【出】SM3结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_SM3(unsigned char *data,unsigned int dataLen, unsigned char *out,unsigned int *outLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_SM4
Description : R5国密SM4运算
Parameter	: data:     入参，数据地址
              dataLen:  入参，数据长度(16字节整数倍，不足需填充)
              mode：    入参，加密模式 0:SM4_ECB , 1:SM4_CBC, 2:SM4_CTR
              useUserKey：入参，是否使用用户秘钥 0：不使用，其他：使用
              key：     入参，秘钥，若使用用户秘钥则key为SRAM密钥ID(按小端序存入如ID:0x12340001 则依次存入01 00 34 12)
              keyLen：  入参，key长度
              isEnc：   入参，是否是加密 0：解密，其他：加密
              ivec：    入参，iv
              ivecLen:  入参，iv长度
              out:     出参，SM4结果
              outLen:  出入参，【入】SM4结果buffer长度,【出】SM4结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_SM4(unsigned char *data, unsigned int dataLen, int mode, int useUserKey, unsigned char *key, unsigned int keyLen,
    unsigned char *ivec, unsigned int ivecLen, int isEnc, unsigned char *dataOut, unsigned int dataOutLen) ;

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_GetLifeStage
Description : R5获取芯片当前生命周期状态
Parameter	: lifeStage:     出参，芯片当前生命周期状态，生命周期状态有如下值：
                    0x24680000：STAGE_INIT,
                    0x24680001：STAGE_PILOT,
                    0x24680002：STAGE_MASS, 
                    0x24680003：STAGE_FAIL,
                    0x24680004：STAGE_END,
                    0x24680005：STAGE_DEV
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_GetLifeStage(unsigned int *lifeStage);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_SetLifeStage
Description : R5设置芯片当前生命周期状态
Parameter	: lifeStage:     入参，要设置的芯片生命周期状态值
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_SetLifeStage(unsigned int lifeStage);

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_SetUserKey
Description : 设置R5 SRAM中的用户密钥（多次设置同一个keyId的密钥时，后者会覆盖前者）
    功能1：用户密钥为R5派生。
            keyId：用户密钥的ID，范围0x12340000 ~ 0x12340003
            key：派生ID的地址，派生ID不同，派生的密钥不同。
                 当用户密钥为0x12340000时，派生ID固定为1；当用户密钥ID为其他值时，派生ID值范围：2~0xf0000000。
            keyLen：无效。
    功能2：设置用户密钥
            keyId：用户密钥的ID，范围0x12340004 ~ 0x12340007
            key：用户密钥的首地址
                注：key为user root key加密后的密文，默认使用user root key前128bit进行加密，当设置KeyFlag后（r5_SetUesrKeyFlag），使用后128bit进行加密（AES_CBC 128，iv=key）。
            keyLen：用户密钥的字节长度（最大为32字节）
    注意事项：
    1)多次设置同一个keyId的用户密钥时，后者会覆盖前者。
    2)掉电后失效。
Parameter	: keyId:    入参，用户keyid，设置派生密钥时，范围0x12340000 ~ 0x12340003
                                         设置用户密钥时，范围0x12340004 ~ 0x12340007
              key:   入参，派生ID地址（设置派生密钥时）
                           密钥首地址（设置用户密钥时）
              keyLen: 入参，密钥的字节长度（最大为32字节，设置用户密钥时有效）
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_SetUserKey(unsigned int keyId, unsigned char *key, unsigned int keyLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_SetUesrKeyFlag
Description : 设置keyFlag标志
              调用本接口后，使用user root key密钥的后128bit加解密用户密钥。
              重要：本接口调用一次，永久有效，不可更改（烧写OTP）。
Parameter	: 无
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_SetUesrKeyFlag(void); 

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_EnableOtpKey
Description : 设置“Force OTP Key”标志
              设置本标志后，安全启动启用SBL验签功能
              重要：本接口调用一次，永久有效，不可更改（烧写OTP）。
Parameter	: 无
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_EnableOtpKey(void);

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_GetKeyStatus
Description : 获取密钥烧录状态
Parameter	: keyId：密钥ID，不同的ID代表不同的密钥
              0xabcd0000：SBL验签秘钥
              0xabcd0001：User Root Key     
              0xabcd0004：sbrHmac密钥
Return		: 0-未烧录密钥，1-已烧录密钥，其他值-获取失败
---------------------------------------------------------------------------------------*/
int libsec_r5_GetKeyStatus(unsigned int keyId);


/*--------------------------------------------------------------------------------------
Function	: libsec_r5_GetChipid
Description : 获取Chipid
Parameter	: id：出参，uint64_t数组，大小至少为2（16字节）
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_GetChipid(uint64_t *id);

int libsec_inquire_version(void *data, uint32_t *data_len);

/*--------------------------------------------------------------------------------------
Function	: Symmetry_encrypt
Description : OPTEE-CA，对称加解密算法（AES）之加密
Parameter	: data, data_len:        入参，需要加密的数据，以及数据长度
              key, key_len:          入参，用于加密的秘钥，以及秘钥长度
              ivec, ivec_len:        入参，可选项，当ivec不为空时，采用AES-CBC模式进行加密，否则为AES-ECB模式，ivec_len为其长度，最大值为16
              encrypt, encrypt_len:  出参，需要保存的加密结果，以及结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int Symmetry_encrypt(unsigned char *data, unsigned int data_len, 
                unsigned char *key, unsigned int key_len, 
                unsigned char *ivec, unsigned int ivec_len, 
                unsigned char *encrypt, unsigned int *encrypt_len);
/*--------------------------------------------------------------------------------------
Function	: Symmetry_decrypt
Description : OPTEE-CA，对称加解密算法（AES）之解密
Parameter	: data, data_len:        入参，需要解密的数据，以及数据长度
              key, key_len:          入参，用于解密的秘钥，以及秘钥长度
              ivec, ivec_len:        入参，可选项，当ivec不为空时，采用AES-CBC模式进行解密，否则为AES-ECB模式，ivec_len为其长度，最大值为16
              decrypt, decrypt_len:  出参，需要保存的解密结果，以及结果长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int Symmetry_decrypt(unsigned char *data, unsigned int data_len, 
                unsigned char *key, unsigned int key_len, 
                unsigned char *ivec, unsigned int ivec_len, 
                unsigned char *decrypt, unsigned int *decrypt_len);

int optee_AES_encrypt(SEC_AES_MODE mode, SEC_AES_TYPE enc, unsigned char *data, unsigned int data_len, 
                unsigned char *key, unsigned int key_len, unsigned char *ivec, unsigned int ivec_len,
                unsigned char *encrypt, unsigned int *encrypt_len);

/*--------------------------------------------------------------------------------------
Function	: libsec_r5_AES_encrypt
Description : 使用R5用户密钥进行AES加解密接口
Parameter	: mode:     入参，AES加解密类型(ECB/CBC/CTR)
              enc:      入参，加密/解密
              data/dataLen:  入参，原始数据及长度（应是16字节倍数）
              keyLen:  入参，密码长度(16/24/32 Bytes)
              keyMode: 入参，目前仅支持使用R5 SRAM的用户密钥进行加解密，值为1
              keyIdx:  入参，用户密钥序号（0x12340000~0x12340007）
              ivec:    入参，向量，长度为16字节，如果输入长度不够16字节，不够部分填充0，ECB模式下为空
              dataOut: 出参，加密后数据（注：需保证内存足够大，加密后数据长度为16字节倍数，且大于等于原始数据长度）
              dataOutLen:  出入参，入参时指示_dataOut大小，出参时指示_dataOut数据长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_r5_AES_encrypt(SEC_AES_MODE mode, SEC_AES_TYPE enc, unsigned char *data, unsigned int dataLen,
    SEC_AES_KEYLEN keyLen, SEC_KEYMODE keyMode, unsigned int keyIdx, unsigned char *ivec, unsigned int ivecLen,
    unsigned char *dataOut, unsigned int *dataOutLen);

/*--------------------------------------------------------------------------------------
Function	: Asymmetry_RSA_keygen
Description : OPTEE-CA，非对称加解密算法（RSA）之生成秘钥
Parameter	: key_len:   入参，想要生成的秘钥的长度
              pub_key:    出参，需要保存的公钥结构
              pri_key:    出参，需要保存的私钥结构
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int Asymmetry_RSA_keygen(size_t key_len, RSA_pubkey pub_key, RSA_prikey pri_key);
/*--------------------------------------------------------------------------------------
Function	: Asymmetry_RSA_encrypt
Description : OPTEE-CA，非对称加解密算法（RSA）之加密
Parameter	: data, data_len:        入参，需要加密的数据，以及数据长度
              encrypt, encrypt_len:  出参，需要保存的加密结果，以及结果长度
              pub_key, key_len:       入参，用于加密的公钥结构，以及秘钥长度
              padding_enc:           入参，用于选择RSA算法的填充模式              
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int Asymmetry_RSA_encrypt(char *data, size_t data_len,                  
                char *encrypt, size_t *encrypt_len, 
                RSA_pubkey pub_key, size_t key_len, uint32_t padding_enc);

int Asymmetry_RSA_decrypt(char *data, size_t data_len,                 
                char *decrypt, size_t *decrypt_len, 
                RSA_prikey pri_key, size_t key_len, uint32_t padding_enc);
                
int Asymmetry_RSA_sign(char *data, size_t data_len,                 
                char *signature, size_t *sign_len, 
                RSA_prikey pri_key, size_t key_len, uint32_t alg_enc);

int Asymmetry_RSA_verify(char *data, size_t data_len,                 
                char *signature, size_t sign_len, 
                RSA_pubkey pu_bkey, size_t key_len, uint32_t alg_enc);
int Asymmetry_RSA_auto(void);


int Asymmetry_ECC_keygen(size_t key_len, size_t alg_enc, ECC_pubkey pub_key, ECC_prikey pri_key);

int Asymmetry_ECC_encrypt(char *data, size_t data_len, 
                char *encrypt, size_t *encrypt_len, 
                ECC_pubkey pub_key, size_t key_len);

int Asymmetry_ECC_decrypt(char *data, size_t data_len, 
                char *decrypt, size_t *decrypt_len, 
                ECC_prikey pri_key, size_t key_len);

int Asymmetry_ECC_sign(char *data, size_t data_len, 
                char *signature, size_t *sign_len, 
                ECC_prikey pri_key, size_t key_len);
int Asymmetry_ECC_verify(char *data, size_t data_len, 
                char *signature, size_t sign_len, 
                ECC_pubkey pub_key, size_t key_len);

//int Symmetry_test(char *data, size_t data_len, char *key, size_t key_len, char *ivec, size_t ivec_len);

int libsec_r5_en_HUK(void);


/*--------------------------------------------------------------------------------------
Function	: libsec_storage_read_data
Description : 从到安全存储区读取数据
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              data:     出参，读取数据的buffer地址
              data_len: 出入参，入参作为需要读取的数据长度，出参为实际读取的数据长度
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_read_data(char *id, char *data, uint32_t *data_len, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_storage_write_data
Description : 保存数据到安全存储区，附带有创建存储单元object的功能
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              data:     入参，需要存储的数据
              data_len: 入参，需要存储的数据长度
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_write_data(char *id, char *data, uint32_t data_len, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_storage_delete_object
Description : 删除保存的数据
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_delete_object(char *id, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_storage_read_data_ex
Description : 从到安全存储区读取数据
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              data:     出参，读取数据的buffer地址
              data_len: 出入参，入参作为需要读取的数据长度，出参为实际读取的数据长度
              offset:   入参，读取位置的偏移量，为负数时从后往前偏移
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_read_data_ex(char *id, char *data, uint32_t *data_len, int offset, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_storage_update_data
Description : 更新数据到安全存储区
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              data:     入参，需要更新的数据地址
              data_len: 入参，需要更新的数据长度
              offset:   入参，更新位置的偏移量，为负数时从后往前偏移
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_update_data(char *id, char *data, uint32_t data_len, int offset, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_storage_delete_object
Description : 保留指定长度的数据
Parameter	: id：      入参，唯一标志存储数据单元object的ID
              size:     入参，需要保留的数据的长度
              sp:       入参，指定存储分区
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_storage_truncate_data(char *id, uint32_t data_len, uint8_t sp);

/*--------------------------------------------------------------------------------------
Function	: libsec_AES_Encrypt
Description : AES 加解密通用接口
Parameter	: cyberModule：入参，加解密系统（OPTEE/R5/..）
              mode:     入参，AES加解密类型(ECB/CBC/CTR)
              enc:      入参，加密/解密
              data/dataLen:  入参，原始数据及长度（因加密算法保证是16字节倍数，因此datalen也应该为16字节倍数，否则解密数据可能不正确）
              key:     入参，密码(仅支持 16/24/32 Bytes其中一种长度)
              ivec:    入参，向量，长度为16字节，如果输入长度不够16字节，不够部分填充0，ECB模式下为空
              dataOut: 出参，加密后数据（注：需保证内存足够大，加密后数据长度为16字节倍数，且大于等于原始数据长度）
              dataOutLen:  出入参，入参时指示_dataOut大小，出参时指示_dataOut数据长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_AES_Encrypt(int cyberModule, SEC_AES_MODE mode, SEC_AES_TYPE enc, unsigned char *data,
    unsigned int dataLen, unsigned char *key, unsigned int keyLen, unsigned char *ivec,
    unsigned int ivecLen, unsigned char *dataOut, unsigned int *dataOutLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_EccSign
Description : R5 ECC签名
Parameter	: data      入参，待签名数据首地址
              dataLen:  入参，待签名数据长度
              mode:     入参，椭圆曲线类型，目前只支持 0：prime256v1
              priKey：  入参，ECC私钥数据的首地址
              priKeyLen：入参，ECC私钥数据长度
              r：       出参，ECC签名值r
              rLen：    出入参，入参时指示r空间大小，出参时指示r数据长度
              s：       出参，ECC签名值s
              sLen：    出入参，入参时指示s空间大小，出参时指示s数据长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_EccSign(unsigned char *data, unsigned int dataLen, int mode, unsigned char *priKey, unsigned int priKeyLen,
     unsigned char *r, unsigned int *rLen,unsigned char *s, unsigned int *sLen);

/*--------------------------------------------------------------------------------------
Function	: libsec_R5_EccVerify
Description : R5 ECC验签
Parameter	: data      入参，待签名数据首地址
              dataLen:  入参，待签名数据长度
              mode:     入参，椭圆曲线类型，目前只支持 0：prime256v1
              pubKeyX   入参，ECC公钥数据X的首地址
              pubKeyXLen：入参，ECC公钥数据X长度
              pubKeyY   入参，ECC公钥数据X的首地址
              pubKeyYLen：入参，ECC公钥数据X长度
              r：       入参，ECC签名值r
              rLen：    入参，r数据长度
              s：       入参，ECC签名值s
              sLen：    入参，s数据长度
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_EccVerify(unsigned char *data, unsigned int dataLen, int mode, unsigned char *pubKeyX, unsigned int pubKeyXLen,
     unsigned char *pubKeyY, unsigned int pubKeyYLen, unsigned char *r, unsigned int rLen,unsigned char *s, unsigned int sLen);
     
/*--------------------------------------------------------------------------------------
Function	: libsec_R5_GetAntiRollbackInfo
Description : R5获取防回滚信息
Parameter	: info：出参，防回滚信息
              len: 入参，info的空间大小（不低于824字节）
                   注意：info中的数据为结构体T_ROLL_BACK_INFO（定义在r5.h）的内存拷贝，将info再次转换成结构体要注意大小端问题。r5是小端。
Return		: SEC_SUCCESS / SEC_ERROR_CODE
---------------------------------------------------------------------------------------*/
int libsec_R5_GetAntiRollbackInfo(unsigned char *info, unsigned int len);

#if defined(__cplusplus)
}
#endif


#endif /* __LIBSECURITY_H */




